﻿using System;
using System.Collections.Generic;
using MongoDB.Bson.Serialization.Attributes;

namespace Sustainalytics.Entities
{
    public class PortfolioDetails : IEntity
    {
        public Guid Id { get; set; }
        public Guid PortfolioId { get; set; }
        public DisplayInformation DisplayInfo { get; set; }
        public MatchedInformation MatchedInfo { get; set; }
        public Guid CompanyId { get; set; }
        public string CompanyNameUrlFriendly { get; set; }
        public string CompanyNameLowercase { get; set; }
        public string SecurityId { get; set; }

        [BsonIgnoreIfNull]
        public bool IsInvalidMatch { get; set; }

        [BsonIgnoreIfNull]
        public double? SecurityWeight { get; set; }

        public PortfolioUserInput GetPortfolioUserInput(Guid addedByUserId)
        {
            return new PortfolioUserInput
            {
                Id = Id,
                InsertDate = DateTime.Today,
                PortfolioId = PortfolioId,
                SecurityIdentifier = DisplayInfo.SecurityIdentifier,
                SecurityName = DisplayInfo.CustomSecurityIdentifierName,
                UserId = addedByUserId
            };
        }
    }

    public class CustomPortfolioDetails : PortfolioDetails { }

    public class SystemPortfolioDetails : PortfolioDetails { }

    public class DisplayInformation : IEquatable<DisplayInformation>
    {
        public DisplayInformation() : this(string.Empty, string.Empty)
        {

        }

        public DisplayInformation(string securityIdentifier, string customSecurityIdentifierName)
        {
            SecurityIdentifier = securityIdentifier;
            CustomSecurityIdentifierName = customSecurityIdentifierName;
        }

        public bool Equals(DisplayInformation other)
        {
            if (ReferenceEquals(null, other))
            {
                return false;
            }
            if (ReferenceEquals(this, other))
            {
                return true;
            }
            return string.Equals(SecurityIdentifier, other.SecurityIdentifier) && string.Equals(CustomSecurityIdentifierName, other.CustomSecurityIdentifierName);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
            {
                return false;
            }
            if (ReferenceEquals(this, obj))
            {
                return true;
            }
            if (obj.GetType() != this.GetType())
            {
                return false;
            }
            return Equals((DisplayInformation)obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                return ((SecurityIdentifier != null ? SecurityIdentifier.GetHashCode() : 0) * 397) ^ (CustomSecurityIdentifierName != null ? CustomSecurityIdentifierName.GetHashCode() : 0);
            }
        }

        public static bool operator ==(DisplayInformation left, DisplayInformation right)
        {
            return Equals(left, right);
        }

        public static bool operator !=(DisplayInformation left, DisplayInformation right)
        {
            return !Equals(left, right);
        }

        public string SecurityIdentifier { get; set; }
        public string CustomSecurityIdentifierName { get; set; }
    }

    public class MatchedInformation : IEquatable<MatchedInformation>
    {
        public MatchedInformation() : this(string.Empty, string.Empty)
        {
        }

        public MatchedInformation(string capitalIQId, string companyName)
        {
            CapitalIQId = capitalIQId;
            CompanyName = companyName;
        }

        public string CapitalIQId { get; set; }
        public string CompanyName { get; set; }
        

        public bool Equals(MatchedInformation other)
        {
            if (ReferenceEquals(null, other))
            {
                return false;
            }
            if (ReferenceEquals(this, other))
            {
                return true;
            }
            return string.Equals(CapitalIQId, other.CapitalIQId) && string.Equals(CompanyName, other.CompanyName);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
            {
                return false;
            }
            if (ReferenceEquals(this, obj))
            {
                return true;
            }
            if (obj.GetType() != this.GetType())
            {
                return false;
            }
            return Equals((MatchedInformation)obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                return ((CapitalIQId != null ? CapitalIQId.GetHashCode() : 0) * 397) ^ (CompanyName != null ? CompanyName.GetHashCode() : 0);
            }
        }

        public static bool operator ==(MatchedInformation left, MatchedInformation right)
        {
            return Equals(left, right);
        }

        public static bool operator !=(MatchedInformation left, MatchedInformation right)
        {
            return !Equals(left, right);
        }
    }
}
